package com.tianji.learning.task;

import com.tianji.common.utils.CollUtils;
import com.tianji.common.utils.DateUtils;
import com.tianji.learning.constant.LearningConstants;
import com.tianji.learning.constant.RedisConstants;
import com.tianji.learning.domain.po.PointsBoard;
import com.tianji.learning.service.IPointsBoardSeasonService;
import com.tianji.learning.service.IPointsBoardService;
import com.tianji.learning.util.TableInfoContext;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.List;

/**
 * @author Xinxuan Zhuo
 * @version 2024/3/18
 * <p>
 *
 * </p>
 */

@Component
@RequiredArgsConstructor
public class PointsBoardPersistentHandlerJob {

    // 赛季服务，获取赛季的id
    private final IPointsBoardSeasonService seasonService;

    // 历史排行榜，创建表
    private final IPointsBoardService pointsBoardService;

    // redis
    private final StringRedisTemplate stringRedisTemplate;


    /**
     * 创建上个月的排行榜表
     */
//    @Scheduled(cron = "0 0 3 1 * ?") // 每月1号，凌晨3点执行
    @XxlJob("createTableJob")
    public void createPointsBoardTableOfLastSeason() {
        // 获取上个月时间
        LocalDateTime time = LocalDateTime.now().minusMonths(1);
        // 查询赛季表，获取赛季id
        Integer seasonId = seasonService.querySeasonByTime(time);
        if (seasonId == null) {
            return;
        }
        // 根据赛季id创建表
        pointsBoardService.createPointsBoardTableBySeason(seasonId);
    }

    /**
     * 将用户排行榜数据写入排行榜表
     */
    @XxlJob("savePointsBoard2DB")
    public void savePointsBoard2DB() {
        //获取上个月的日期
        LocalDateTime time = LocalDateTime.now().minusMonths(1);
        // 查询上个赛季的id
        Integer seasonId = seasonService.querySeasonByTime(time);
        //拼接表名，并放入ThreadLocal
        TableInfoContext.set(LearningConstants.POINTS_BOARD_TABLE_PREFIX + seasonId);
        // 拼接key 查询redis中的上月榜单数据
        String key = RedisConstants.POINTS_BOARD_KEY_PREFIX + time.format(DateUtils.POINTS_BOARD_SUFFIX_FORMATTER);
        int index = XxlJobHelper.getShardIndex();
        int total = XxlJobHelper.getShardTotal();
        int pageNo = index + 1; // 起始页，就是分片序号+1
        int pageSize = 10;
        // 为空直接return
        while (true) {
            List<PointsBoard> boardList = pointsBoardService.queryCurrentBoardList(key, pageNo, pageSize);
            if (CollUtils.isEmpty(boardList)) {
                break;
            }
            // 持久化到数据库
            // 把排名信息写入id
            boardList.forEach(b -> {
                b.setId(b.getRank().longValue());
                b.setRank(null);
            });
            // 持久化
            pointsBoardService.saveBatch(boardList);
            // 翻页，跳过N个页，N就是分片数量
            pageNo += total;
        }
        // 清除缓存
        TableInfoContext.remove();
    }


    /**
     * 清空redis上月的用户排行榜数据
     */
    @XxlJob("clearPointsBoardFromRedis")
    public void clearPointsBoardFromRedis() {
        // 1.获取上月时间
        LocalDateTime time = LocalDateTime.now().minusMonths(1);
        // 2.计算key
        String key = RedisConstants.POINTS_BOARD_KEY_PREFIX + time.format(DateUtils.POINTS_BOARD_SUFFIX_FORMATTER);
        // 3.删除
        stringRedisTemplate.unlink(key);
    }

}
